package atom.core3.redis;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import atom.core0.util.StringUtil;
import atom.core2.j2ee.util.MyCookieManager;

/**
 * @author aps-zmc
 * 
 *         jedis.close(); pool.returnResource(jedis);在3.0以后中将废弃
 * 
 *         session 信息以Hashes类型 存储，即是个MAP 浏览器
 *         本想也是以jsessionid存储，但是担心被容器认为非法，所以自定义cookies.而且，也无法控制jsessionid的域
 */

public class RedisSession {
	//private static JedisSentinelPool jedisPool = null;
	private static String JedisSessionCookieName = "MySessionID";// cookies值的命名规则可以sessionid_xxxxxxx
	private static String domain = "";// cookies值的命名规则可以sid_xxxxxxx
	private static int timeout = 0;
	private static String sessionidPrefix = "sid";// 管理平台的最好区分开 设置下 msid
	private static String deviceidPrefix = "deviceid_";

	// 可以使用JSESSIONID 但是不同容器的JSESSIONID的规则可能不同，jboss生成的不能用于tomcat和jetty
	public static void initSessionID(String sessionIDName) {
		JedisSessionCookieName = sessionIDName;
	}

	public static void initDomain(String domainName) {
		domain = domainName;
	}

	// 秒, 0临时,-1永久
	public static void initSessionTimeout(int ntimeout) {
		timeout = ntimeout;
	}

	public static void initJedisSentinels(String masterName, HashSet<String> ipport, String password) {
		JedisSentinelPool jedisPool;
		if (StringUtil.isEmpty(password))
			jedisPool = new JedisSentinelPool(masterName, ipport);
		else
			jedisPool = new JedisSentinelPool(masterName, ipport, password);
		
		JedisSentinelPoolManager.setJedisSentinelPool(jedisPool);
	}

	public static void initSessionidPrefix(String sessionidPrefix) {
		RedisSession.sessionidPrefix = sessionidPrefix;
	}

	// 增量增加session
	public static void setSession(HttpServletRequest request, HttpServletResponse response, Map<String, String> sessMap) {
		// String sessionid = request.getSession().getId();// JSESSIONID
		String sessionid = MyCookieManager.getCookieValue(request, JedisSessionCookieName);
		if (StringUtil.isEmpty(sessionid)) {
			sessionid = UUID.randomUUID().toString();
			Cookie cookie = new Cookie(JedisSessionCookieName, sessionid);
			// cookie.setMaxAge(timeout);
			cookie.setPath("/");
			if (!StringUtil.isEmpty(domain))
				cookie.setDomain(domain);
			response.addCookie(cookie);

		}

		Jedis jedis = JedisSentinelPoolManager.getJedisSentinelPool().getResource();
		try {
			sessionid = sessionidPrefix + "_" + sessionid;
			// jedis.del(sessionid); 不删除了，增量增加
			Iterator it = sessMap.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry entry = (Map.Entry) it.next();
				String key = (String) entry.getKey();
				String value = (String) entry.getValue();
				jedis.hset(sessionid, key, value);

			}

			setTimeout(jedis, sessionid);
		} finally {
			JedisSentinelPoolManager.getJedisSentinelPool().returnResource(jedis);
		}
	}

	// 增量session
	public static void setSession(HttpServletRequest request, HttpServletResponse response, String key, String value) {
		// String sessionid = request.getSession().getId();// JSESSIONID
		String sessionid = MyCookieManager.getCookieValue(request, JedisSessionCookieName);
		if (StringUtil.isEmpty(sessionid)) {
			sessionid = UUID.randomUUID().toString();
			Cookie cookie = new Cookie(JedisSessionCookieName, sessionid);
			// cookie.setMaxAge(timeout);
			cookie.setPath("/");
			if (!StringUtil.isEmpty(domain))
				cookie.setDomain(domain);
			response.addCookie(cookie);
		}
		Jedis jedis = JedisSentinelPoolManager.getJedisSentinelPool().getResource();
		try {
			sessionid = sessionidPrefix + "_" + sessionid;
			jedis.hset(sessionid, key, value);
			setTimeout(jedis, sessionid);
		} finally {
			JedisSentinelPoolManager.getJedisSentinelPool().returnResource(jedis);
		}

	}

	public static Map<String, String> getSession(HttpServletRequest request) {
		// String sessionid = request.getSession().getId();// JSESSIONID
		String sessionid = MyCookieManager.getCookieValue(request, JedisSessionCookieName);
		if (StringUtil.isEmpty(sessionid)) {
			return null;
		}
		Jedis jedis = JedisSentinelPoolManager.getJedisSentinelPool().getResource();

		sessionid = sessionidPrefix + "_" + sessionid;
		Map map = jedis.hgetAll(sessionid);

		setTimeout(jedis, sessionid);
		JedisSentinelPoolManager.getJedisSentinelPool().returnResource(jedis);
		return map;

	}

	public static String getSession(HttpServletRequest request, String key) {
		// String sessionid = request.getSession().getId();// JSESSIONID

		String sessionid = MyCookieManager.getCookieValue(request, JedisSessionCookieName);
		if (StringUtil.isEmpty(sessionid)) {
			return null;
		}
		Jedis jedis = JedisSentinelPoolManager.getJedisSentinelPool().getResource();
		String value="";
		try {
			sessionid = sessionidPrefix + "_" + sessionid;
			value = jedis.hget(sessionid, key);
			setTimeout(jedis, sessionid);
		} finally {
			JedisSentinelPoolManager.getJedisSentinelPool().returnResource(jedis);
			
		}
		return value;
		

	}

	public static boolean isValidSession(HttpServletRequest request) {
		// String sessionid = request.getSession().getId();// JSESSIONID

		String sessionid = MyCookieManager.getCookieValue(request, JedisSessionCookieName);
		if (StringUtil.isEmpty(sessionid)) {
			return false;
		}
		Jedis jedis = JedisSentinelPoolManager.getJedisSentinelPool().getResource();

		sessionid = sessionidPrefix + "_" + sessionid;
		return jedis.exists(sessionid);

	}

	public static void setTimeout(Jedis jedis, String sessionid) {
		// +600秒，尽量让cookies先过期 如果cookies的过期时间是0或者-1，则固定过期时间3600秒
		if (timeout <= 0)
			jedis.expire(sessionid, 3600);
		else
			jedis.expire(sessionid, timeout);// +600
	}

	public static void printSessions(Jedis jedis) {
		Set s = jedis.keys(sessionidPrefix + "_*");
		Iterator it = s.iterator();

		while (it.hasNext()) {
			String key = (String) it.next();
			Map value = jedis.hgetAll(key);
			long lk = jedis.ttl(key);
			// 查看某个key的剩余生存时间,单位【秒】.永久生存或者不存在的都返回-1
			System.out.println(key + "=" + value + ";time=" + lk);
		}
	}

	public static JedisSentinelPool getJedisPool() {
		return JedisSentinelPoolManager.getJedisSentinelPool();
	}

	public static void setJedisPool(JedisSentinelPool jedisPool) {
		JedisSentinelPoolManager.setJedisSentinelPool(jedisPool);
	}

	public static void deleteSession(HttpServletRequest request) {
		String sessionid = MyCookieManager.getCookieValue(request, JedisSessionCookieName);
		if (StringUtil.isEmpty(sessionid)) {
			return;
		}
		Jedis jedis = JedisSentinelPoolManager.getJedisSentinelPool().getResource();

		sessionid = sessionidPrefix + "_" + sessionid;
		jedis.del(sessionid);
		JedisSentinelPoolManager.getJedisSentinelPool().returnResource(jedis);

	}

	public static boolean checkLastLoginDevice(HttpServletRequest request) {
		String usr_no = RedisSession.getSession(request, "usr_no");
		String session_deviceid = RedisSession.getSession(request, "last_deviceid");

		Jedis jedis = JedisSentinelPoolManager.getJedisSentinelPool().getResource();
		String last_deviceid = jedis.get(deviceidPrefix + usr_no);
		//如果最新登陆的设备号没记录在redies里面，则认为不需要检查，则放行
		if (StringUtil.isEmpty(last_deviceid))
			return true;		
		// 比较session_deviceid 与 last_deviceid 如果不一致，说明在新设备上登陆了
		if (last_deviceid.compareTo(session_deviceid) == 0) {
			setTimeout(jedis, deviceidPrefix + usr_no);
			jedis.close();
			return true;
		}
		jedis.close();
		return false;
	}

	public static void setLastLoginDevice(String usr_no, String last_deviceid)// HttpServletRequest
																				// request
	{
		// String usr_no = RedisSession.getSession(request, "usr_no");
		// String last_deviceid = RedisSession.getSession(request,
		// "last_deviceid");

		if (StringUtil.isEmpty(usr_no))
			return;
		if (StringUtil.isEmpty(last_deviceid))
			return;
		Jedis jedis = JedisSentinelPoolManager.getJedisSentinelPool().getResource();
		jedis.set(deviceidPrefix + usr_no, last_deviceid);
		setTimeout(jedis, deviceidPrefix + usr_no);
		jedis.close();
		return;
	}
}
